{
  "cells": [
    {
      "metadata": {
        "id": "zWgEkOAO9OVz"
      },
      "cell_type": "markdown",
      "source": [
        "# An example illustrating how to use the inventory component.\n",
        "\n"
      ]
    },
    {
      "metadata": {
        "id": "P10tx4PO3vL8"
      },
      "cell_type": "markdown",
      "source": [
        "\u003ca href=\"https://colab.research.google.com/github/google-deepmind/concordia/blob/main/examples/deprecated/magic_beans_for_sale.ipynb\" target=\"_parent\"\u003e\u003cimg src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/\u003e\u003c/a\u003e"
      ]
    },
    {
      "metadata": {
        "id": "J2TwJrZ08wXz"
      },
      "cell_type": "markdown",
      "source": [
        "## Setup and imports"
      ]
    },
    {
      "metadata": {
        "id": "ibSOXvFOEs7H"
      },
      "cell_type": "code",
      "source": [
        "# @title Colab-specific setup (use a CodeSpace to avoid the need for this).\n",
        "try:\n",
        "  %env COLAB_RELEASE_TAG\n",
        "except:\n",
        "  pass  # Not running in colab.\n",
        "else:\n",
        "  %pip install --ignore-requires-python --requirement 'https://raw.githubusercontent.com/google-deepmind/concordia/main/examples/requirements.in' 'git+https://github.com/google-deepmind/concordia.git#egg=gdm-concordia'\n",
        "  %pip list"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "-qLG5ExLqpWa"
      },
      "cell_type": "code",
      "source": [
        "# @title Imports\n",
        "\n",
        "import collections\n",
        "import concurrent.futures\n",
        "import datetime\n",
        "\n",
        "import matplotlib.pyplot as plt\n",
        "import numpy as np\n",
        "import sentence_transformers\n",
        "\n",
        "from IPython import display\n",
        "\n",
        "from concordia.agents.deprecated import deprecated_agent as basic_agent\n",
        "from concordia.components import deprecated as generic_components\n",
        "from concordia.associative_memory.deprecated import associative_memory\n",
        "from concordia.associative_memory.deprecated import blank_memories\n",
        "from concordia.associative_memory.deprecated import formative_memories\n",
        "from concordia.associative_memory.deprecated import importance_function\n",
        "from concordia.clocks import game_clock\n",
        "from concordia.components.agent.deprecated import to_be_deprecated as components\n",
        "from concordia.components.game_master import deprecated as gm_components\n",
        "from concordia.environment.deprecated import game_master\n",
        "from concordia.contrib.language_models.openai import gpt_model\n",
        "from concordia.deprecated.metrics import goal_achievement\n",
        "from concordia.deprecated.metrics import common_sense_morality\n",
        "from concordia.deprecated.metrics import opinion_of_others\n",
        "from concordia.utils import html as html_lib\n",
        "from concordia.utils.deprecated import measurements as measurements_lib\n",
        "from concordia.utils import plotting\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "I3OtW8flCJSC"
      },
      "cell_type": "code",
      "source": [
        "# Setup sentence encoder\n",
        "st_model = sentence_transformers.SentenceTransformer(\n",
        "    'sentence-transformers/all-mpnet-base-v2')\n",
        "embedder = lambda x: st_model.encode(x, show_progress_bar=False)"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "cugwvFIKv5AS"
      },
      "cell_type": "code",
      "source": [
        "# @title Language Model - pick your model and provide keys\n",
        "\n",
        "# By default this colab uses GPT-4, so you must provide an API key.\n",
        "# Note that it is also possible to use local models or other API models,\n",
        "# simply replace this cell with the correct initialization for the model\n",
        "# you want to use.\n",
        "GPT_API_KEY = '' #@param {type: 'string'}\n",
        "GPT_MODEL_NAME = 'gpt-4o' #@param {type: 'string'}\n",
        "\n",
        "if not GPT_API_KEY:\n",
        "  raise ValueError('GPT_API_KEY is required.')\n",
        "\n",
        "model = gpt_model.GptLanguageModel(api_key=GPT_API_KEY,\n",
        "                                   model_name=GPT_MODEL_NAME)\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "z9HYjZgyakc_"
      },
      "cell_type": "markdown",
      "source": [
        "## Configuring the generic knowledge of players and GM."
      ]
    },
    {
      "metadata": {
        "id": "TeVYseoD2WYa"
      },
      "cell_type": "code",
      "source": [
        "#@title Make the clock\n",
        "TIME_STEP = datetime.timedelta(minutes=20)\n",
        "SETUP_TIME = datetime.datetime(hour=20, year=2024, month=10, day=1)\n",
        "\n",
        "START_TIME = datetime.datetime(hour=12, year=2024, month=10, day=2)\n",
        "clock = game_clock.MultiIntervalClock(\n",
        "    start=SETUP_TIME,\n",
        "    step_sizes=[TIME_STEP, datetime.timedelta(seconds=10)])\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "otZ6Xg6BnohY"
      },
      "cell_type": "code",
      "source": [
        "#@title Importance models\n",
        "importance_model = importance_function.AgentImportanceModel(model)\n",
        "importance_model_gm = importance_function.ConstantImportanceModel()\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "b8vWoQ6by51N"
      },
      "cell_type": "code",
      "source": [
        "# @title Generic memories are memories that all players and GM share.\n",
        "\n",
        "shared_memories = [\n",
        "    'Riverbend is a small town.',\n",
        "    ('There is a general store in Riverbend called The Oddments and Oddities ' +\n",
        "     'Emporium.'),\n",
        "    'Alice works in the general store.',\n",
        "    'The Oddments and Oddities Emporium sells magic beans.',\n",
        "    'The usual price of a magic bean is $10 per bean.',\n",
        "]\n",
        "\n",
        "# The generic context will be used for the NPC context. It reflects general\n",
        "# knowledge and is possessed by all characters.\n",
        "shared_context = model.sample_text(\n",
        "    'Summarize the following passage in a concise and insightful fashion:\\n'\n",
        "    + '\\n'.join(shared_memories)\n",
        "    + '\\n'\n",
        "    + 'Summary:'\n",
        ")\n",
        "print(shared_context)\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "dGwXtHiGn8H3"
      },
      "cell_type": "markdown",
      "source": [
        "## Configure and build the players\n",
        "\n"
      ]
    },
    {
      "metadata": {
        "id": "QHJ25gnUn0y6"
      },
      "cell_type": "code",
      "source": [
        "blank_memory_factory = blank_memories.MemoryFactory(\n",
        "    model=model,\n",
        "    embedder=embedder,\n",
        "    importance=importance_model.importance,\n",
        "    clock_now=clock.now,\n",
        ")\n",
        "\n",
        "formative_memory_factory = formative_memories.FormativeMemoryFactory(\n",
        "    model=model,\n",
        "    shared_memories=shared_memories,\n",
        "    blank_memory_factory_call=blank_memory_factory.make_blank_memory,\n",
        ")"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "YBCXUQ8sayzj"
      },
      "cell_type": "markdown",
      "source": [
        "## Functions to build the players"
      ]
    },
    {
      "metadata": {
        "id": "NkgQEQ4JoDtZ"
      },
      "cell_type": "code",
      "source": [
        "def build_agent(agent_config,\n",
        "                player_names: list[str],\n",
        "                measurements: measurements_lib.Measurements | None = None):\n",
        "\n",
        "  mem = formative_memory_factory.make_memories(agent_config)\n",
        "\n",
        "  agent_name = agent_config.name\n",
        "  instructions = generic_components.constant.ConstantComponent(\n",
        "      state=(\n",
        "          f'The instructions for how to play the role of {agent_name} are as '\n",
        "          'follows. This is a social science experiment studying how well you '\n",
        "          f'play the role of a character named {agent_name}. The experiment '\n",
        "          'is structured as a tabletop roleplaying game (like dungeons and '\n",
        "          'dragons). However, in this case it is a serious social science '\n",
        "          'experiment and simulation. The goal is to be realistic. It is '\n",
        "          f'important to play the role of a person like {agent_name} as '\n",
        "          f'accurately as possible, i.e., by responding in ways that you think '\n",
        "          f'it is likely a person like {agent_name} would respond, and taking '\n",
        "          f'into account all information about {agent_name} that you have. '\n",
        "          'Always use third-person limited perspective.'\n",
        "      ),\n",
        "      name='role playing instructions\\n')\n",
        "\n",
        "  time = generic_components.report_function.ReportFunction(\n",
        "    name='Current time',\n",
        "    function=clock.current_time_interval_str,\n",
        "  )\n",
        "\n",
        "  current_obs = components.observation.Observation(\n",
        "            agent_name=agent_config.name,\n",
        "      clock_now=clock.now,\n",
        "      memory=mem,\n",
        "      timeframe=clock.get_step_size(),\n",
        "      component_name='current observations',\n",
        "  )\n",
        "\n",
        "  self_perception = components.self_perception.SelfPerception(\n",
        "      name=f'What kind of person is {agent_config.name}? ',\n",
        "      model=model,\n",
        "      memory=mem,\n",
        "      agent_name=agent_config.name,\n",
        "      clock_now=clock.now,\n",
        "      verbose=True,\n",
        "  )\n",
        "  situation_perception = components.situation_perception.SituationPerception(\n",
        "      name=f'What kind of situation is {agent_config.name} in right now? ',\n",
        "      model=model,\n",
        "      memory=mem,\n",
        "      agent_name=agent_config.name,\n",
        "      components=[current_obs],\n",
        "      clock_now=clock.now,\n",
        "      verbose=True,\n",
        "  )\n",
        "  person_by_situation = components.person_by_situation.PersonBySituation(\n",
        "      name=(f'What would a person like {agent_config.name} do in a situation ' +\n",
        "            'like this? '),\n",
        "      model=model,\n",
        "      memory=mem,\n",
        "      agent_name=agent_config.name,\n",
        "      clock_now=clock.now,\n",
        "      components=[self_perception, situation_perception],\n",
        "  )\n",
        "\n",
        "  initial_goal_component = generic_components.constant.ConstantComponent(\n",
        "      state=agent_config.goal)\n",
        "  plan = components.plan.SimPlan(\n",
        "      model,\n",
        "      mem,\n",
        "      agent_config.name,\n",
        "      clock_now=clock.now,\n",
        "      components=[initial_goal_component, person_by_situation],\n",
        "      goal=person_by_situation,\n",
        "      horizon='the next hour',\n",
        "      verbose=False,\n",
        "  )\n",
        "\n",
        "  persona = generic_components.sequential.Sequential(\n",
        "      name='persona',\n",
        "      components=[\n",
        "          self_perception,\n",
        "          situation_perception,\n",
        "          person_by_situation,\n",
        "          plan,\n",
        "      ]\n",
        "  )\n",
        "\n",
        "  summary_obs = components.observation.ObservationSummary(\n",
        "      agent_name=agent_config.name,\n",
        "      model=model,\n",
        "      clock_now=clock.now,\n",
        "      memory=mem,\n",
        "      components=[persona, current_obs],\n",
        "      timeframe_delta_from=datetime.timedelta(hours=4),\n",
        "      timeframe_delta_until=datetime.timedelta(hours=1),\n",
        "      component_name='summary of observations',\n",
        "  )\n",
        "\n",
        "  goal_metric = goal_achievement.GoalAchievementMetric(\n",
        "      model=model,\n",
        "      player_name=agent_config.name,\n",
        "      player_goal=agent_config.goal,\n",
        "      clock=clock,\n",
        "      name='Goal Achievement',\n",
        "      measurements=measurements,\n",
        "      channel='goal_achievement',\n",
        "      verbose=False,\n",
        "  )\n",
        "  morality_metric = common_sense_morality.CommonSenseMoralityMetric(\n",
        "      model=model,\n",
        "      player_name=agent_config.name,\n",
        "      clock=clock,\n",
        "      name='Morality',\n",
        "      verbose=False,\n",
        "      measurements=measurements,\n",
        "      channel='common_sense_morality',\n",
        "  )\n",
        "  agent = basic_agent.BasicAgent(\n",
        "      model,\n",
        "      agent_name=agent_config.name,\n",
        "      clock=clock,\n",
        "      verbose=False,\n",
        "      components=[instructions,\n",
        "                  persona,\n",
        "                  summary_obs,\n",
        "                  current_obs,\n",
        "                  time,\n",
        "                  goal_metric,\n",
        "                  morality_metric],\n",
        "      update_interval = TIME_STEP\n",
        "  )\n",
        "  reputation_metric = opinion_of_others.OpinionOfOthersMetric(\n",
        "      model=model,\n",
        "      player_name=agent_config.name,\n",
        "      player_names=player_names,\n",
        "      context_fn=agent.state,\n",
        "      clock=clock,\n",
        "      name='Opinion',\n",
        "      verbose=False,\n",
        "      measurements=measurements,\n",
        "      channel='opinion_of_others',\n",
        "      question='What is {opining_player}\\'s opinion of {of_player}?',\n",
        "  )\n",
        "  agent.add_component(reputation_metric)\n",
        "  return agent, mem\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "qt8CK2mMbD7q"
      },
      "cell_type": "markdown",
      "source": [
        "## Configure and build the players"
      ]
    },
    {
      "metadata": {
        "id": "YxexdZ6XoR2K"
      },
      "cell_type": "code",
      "source": [
        "#@title Creating character backgrounds, goals and traits. Modify to explore how it influences the outcomes\n",
        "NUM_PLAYERS = 4\n",
        "\n",
        "player_configs = [\n",
        "    formative_memories.AgentConfig(\n",
        "        name='Alice',\n",
        "        gender='female',\n",
        "        goal='Alice wants to sell as many magic beans as possible.',\n",
        "        context='Alice is passionate about selling magic beans.',\n",
        "        traits='responsibility: high; aggression: low',\n",
        "        extras={'initial_endowment': {'money': 20.0, 'magic beans': 100.0},},\n",
        "    ),\n",
        "    formative_memories.AgentConfig(\n",
        "        name='Bob',\n",
        "        gender='male',\n",
        "        goal='Bob wants to buy lots of magic beans to feed a magic cat.',\n",
        "        context='Bob has a magic cat who loves to eat magic beans.',\n",
        "        traits='responsibility: high; aggression: low',\n",
        "        extras={'initial_endowment': {'money': 75.0, 'magic beans': 0.0},},\n",
        "    ),\n",
        "    formative_memories.AgentConfig(\n",
        "        name='Charlie',\n",
        "        gender='male',\n",
        "        goal=(\n",
        "            'Charlie wants to steal magic beans and then open his own shop ' +\n",
        "            'selling them more cheaply than the Oddments and Oddities ' +\n",
        "            'Emporium. By doing that, Charlie hopes to win over their ' +\n",
        "            'customers by offering to sell the same magic beans at a lower ' +\n",
        "            'price.'\n",
        "        ),\n",
        "        context='Charlie is very stealthy and good at sneaking around',\n",
        "        traits='responsibility: low; aggression: high',\n",
        "        extras={'initial_endowment': {'money': 5.0, 'magic beans': 0.0},},\n",
        "    ),\n",
        "]"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "b0vQg5tVqlcs"
      },
      "cell_type": "code",
      "source": [
        "player_configs = player_configs[:NUM_PLAYERS]\n",
        "player_names = [player.name for player in player_configs][:NUM_PLAYERS]\n",
        "measurements = measurements_lib.Measurements()\n",
        "\n",
        "players = []\n",
        "memories = {}\n",
        "with concurrent.futures.ThreadPoolExecutor(max_workers=NUM_PLAYERS) as pool:\n",
        "  for agent, mem in pool.map(build_agent,\n",
        "                             player_configs[:NUM_PLAYERS],\n",
        "                             # All players get the same `player_names`.\n",
        "                             [player_names] * NUM_PLAYERS,\n",
        "                             # All players get the same `measurements` object.\n",
        "                             [measurements] * NUM_PLAYERS):\n",
        "    players.append(agent)\n",
        "    memories[agent.name] = mem\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "2vt8ggYUrW8M"
      },
      "cell_type": "markdown",
      "source": [
        "## Build GM"
      ]
    },
    {
      "metadata": {
        "id": "3W65kHOKQwrv"
      },
      "cell_type": "code",
      "source": [
        "game_master_memory = associative_memory.AssociativeMemory(\n",
        "   sentence_embedder=embedder,\n",
        "   importance=importance_model_gm.importance,\n",
        "   clock=clock.now)"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "-cxivChc633z"
      },
      "cell_type": "code",
      "source": [
        "# @title Create components of the Game Master\n",
        "player_names = [player.name for player in players]\n",
        "\n",
        "scenario_knowledge = generic_components.constant.ConstantComponent(\n",
        "    state=' '.join(shared_memories),\n",
        "    name='Background')\n",
        "time_display=generic_components.report_function.ReportFunction(\n",
        "    name='Current time',\n",
        "    function=clock.current_time_interval_str,\n",
        "  )\n",
        "important_facts = [\n",
        "    'Magic beans are marked \"magical\" but have no actual magical powers.',\n",
        "    'Magic is not real.',\n",
        "]\n",
        "important_facts_construct = generic_components.constant.ConstantComponent(\n",
        "    state=' '.join(important_facts),\n",
        "    name='Important facts')\n",
        "\n",
        "ItemTypeConfig = gm_components.inventory.ItemTypeConfig\n",
        "money_config = ItemTypeConfig(name='money')\n",
        "magic_beans_config = ItemTypeConfig(\n",
        "    name='magic beans', minimum=0, maximum=np.inf, force_integer=True)\n",
        "player_initial_endowments = {\n",
        "    config.name: config.extras['initial_endowment'] for config in player_configs}\n",
        "inventories = gm_components.inventory.Inventory(\n",
        "    model=model,\n",
        "    memory=game_master_memory,\n",
        "    item_type_configs=[money_config, magic_beans_config],\n",
        "    players=players,\n",
        "    player_initial_endowments=player_initial_endowments,\n",
        "    clock_now=clock.now,\n",
        "    financial=True,\n",
        "    name='Property',\n",
        "    verbose=True,\n",
        ")\n",
        "\n",
        "player_status = gm_components.player_status.PlayerStatus(\n",
        "    clock_now=clock.now,\n",
        "    model=model,\n",
        "    memory=game_master_memory,\n",
        "    player_names=player_names)\n",
        "\n",
        "convo_externality = gm_components.conversation.Conversation(\n",
        "    players=players,\n",
        "    model=model,\n",
        "    memory=game_master_memory,\n",
        "    clock=clock,\n",
        "    burner_memory_factory=blank_memory_factory,\n",
        "    components=[player_status, inventories],\n",
        "    cap_nonplayer_characters=3,\n",
        "    shared_context=shared_context,\n",
        "    verbose=False,\n",
        ")\n",
        "\n",
        "direct_effect_externality = gm_components.direct_effect.DirectEffect(\n",
        "    players=players,\n",
        "    model=model,\n",
        "    memory=game_master_memory,\n",
        "    clock_now=clock.now,\n",
        "    verbose=False,\n",
        "    components=[player_status, inventories]\n",
        ")\n",
        "\n",
        "relevant_events = gm_components.relevant_events.RelevantEvents(\n",
        "    clock.now, model, game_master_memory)\n",
        "time_display = gm_components.time_display.TimeDisplay(clock)\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "d_R2BVNOsAwa"
      },
      "cell_type": "code",
      "source": [
        "# @title Create the game master object\n",
        "env = game_master.GameMaster(\n",
        "    model=model,\n",
        "    memory=game_master_memory,\n",
        "    clock=clock,\n",
        "    players=players,\n",
        "    components=[\n",
        "        scenario_knowledge,\n",
        "        important_facts_construct,\n",
        "        player_status,\n",
        "        convo_externality,\n",
        "        direct_effect_externality,\n",
        "        inventories,\n",
        "        relevant_events,\n",
        "        time_display,\n",
        "    ],\n",
        "    randomise_initiative=True,\n",
        "    player_observes_event=False,\n",
        "    verbose=True,\n",
        ")"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "LXykV_TdwfKq"
      },
      "cell_type": "code",
      "source": [],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "d2u0bQ1MSCGd"
      },
      "cell_type": "markdown",
      "source": [
        "## The RUN"
      ]
    },
    {
      "metadata": {
        "id": "hdTRDaxEZZnN"
      },
      "cell_type": "code",
      "source": [
        "clock.set(START_TIME)"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "9IggLF1aH_hF"
      },
      "cell_type": "code",
      "source": [
        "for player in players:\n",
        "  game_master_memory.add(\n",
        "      f'{player.name} is at The Oddments and Oddities Emporium.')\n",
        "\n",
        "scenario_premise = (\n",
        "    'Alice, Bob, and Charlie are at The Oddments and Oddities '\n",
        "    'Emporium.'\n",
        ")\n",
        "game_master_memory.add(scenario_premise)"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "HIFEzzs5pAJW"
      },
      "cell_type": "code",
      "source": [
        "for player in players:\n",
        "  player.observe(scenario_premise)\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "2Bt87stq76gF"
      },
      "cell_type": "code",
      "source": [
        "# @title Expect about 2-3 minutes per step.\n",
        "episode_length = 10  # @param {type: 'integer'}\n",
        "for _ in range(episode_length):\n",
        "  env.step()\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "DnwvpvQ4bnFs"
      },
      "cell_type": "markdown",
      "source": [
        "## Summary and analysis of the episode"
      ]
    },
    {
      "metadata": {
        "id": "5U5FDXvs4HSr"
      },
      "cell_type": "code",
      "source": [
        "# @title Metrics plotting\n",
        "\n",
        "group_by = collections.defaultdict(lambda: 'player')\n",
        "group_by['opinion_of_others'] = 'of_player'\n",
        "\n",
        "available_channels = list(measurements.available_channels())\n",
        "\n",
        "fig, ax = plt.subplots(1, len(available_channels), figsize=(6, 2))\n",
        "tb = [channel for channel in available_channels]\n",
        "for idx, channel in enumerate(available_channels):\n",
        "  plotting.plot_line_measurement_channel(measurements, channel,\n",
        "                                         group_by=group_by[channel],\n",
        "                                         xaxis='time_str',\n",
        "                                         ax=ax[idx])\n",
        "  ax[idx].set_title(channel)\n",
        "\n",
        "fig.set_constrained_layout(constrained=True)"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "i8BO9rOX09xu"
      },
      "cell_type": "markdown",
      "source": [
        "#Build and display HTML log of the experiment"
      ]
    },
    {
      "metadata": {
        "id": "j71OiuPot5UV"
      },
      "cell_type": "markdown",
      "source": [
        "## Prepare to visualize text results with HTML"
      ]
    },
    {
      "metadata": {
        "id": "O4jp0xGXvOAJ"
      },
      "cell_type": "code",
      "source": [
        "# @title Summarize the entire story.\n",
        "all_gm_memories = env._memory.retrieve_recent(k=10000, add_time=True)\n",
        "\n",
        "detailed_story = '\\n'.join(all_gm_memories)\n",
        "print('len(detailed_story): ', len(detailed_story))\n",
        "# print(detailed_story)\n",
        "\n",
        "episode_summary = model.sample_text(\n",
        "    f'Sequence of events:\\n{detailed_story}'+\n",
        "    '\\nNarratively summarize the above temporally ordered ' +\n",
        "    'sequence of events. Write it as a news report. Summary:\\n',\n",
        "     max_tokens=3500, terminators=())\n",
        "print(episode_summary)"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "ALG987t-6j-V"
      },
      "cell_type": "code",
      "source": [
        "# @title Summarise the perspective of each player\n",
        "player_logs = []\n",
        "player_log_names = []\n",
        "for player in players:\n",
        "  name = player.name\n",
        "  detailed_story = '\\n'.join(memories[player.name].retrieve_recent(\n",
        "      k=1000, add_time=True))\n",
        "  summary = ''\n",
        "  summary = model.sample_text(\n",
        "      f'Sequence of events that happened to {name}:\\n{detailed_story}'\n",
        "      '\\nWrite a short story that summarises these events.\\n'\n",
        "      ,\n",
        "       max_tokens=3500, terminators=())\n",
        "\n",
        "  all_player_mem = memories[player.name].retrieve_recent(k=1000, add_time=True)\n",
        "  all_player_mem = ['Summary:', summary, 'Memories:'] + all_player_mem\n",
        "  player_html = html_lib.PythonObjectToHTMLConverter(all_player_mem).convert()\n",
        "  player_logs.append(player_html)\n",
        "  player_log_names.append(f'{name}')\n"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "JyEoGgI05xI0"
      },
      "cell_type": "code",
      "source": [
        "history_sources = [env, direct_effect_externality, convo_externality]\n",
        "histories_html = [\n",
        "    html_lib.PythonObjectToHTMLConverter(history.get_history()).convert()\n",
        "    for history in history_sources]\n",
        "histories_names = [history.name for history in history_sources]"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "XNJuo4Dwt5Ui"
      },
      "cell_type": "code",
      "source": [
        "gm_mem_html = html_lib.PythonObjectToHTMLConverter(all_gm_memories).convert()\n",
        "\n",
        "tabbed_html = html_lib.combine_html_pages(\n",
        "    histories_html + [gm_mem_html] + player_logs,\n",
        "    histories_names + ['GM'] + player_log_names,\n",
        "    summary=episode_summary,\n",
        "    title='Magic beans experiment',\n",
        ")\n",
        "\n",
        "tabbed_html = html_lib.finalise_html(tabbed_html)"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "pumxvmrzANOq"
      },
      "cell_type": "code",
      "source": [
        "# @title Display the HTML log visualization\n",
        "display.HTML(tabbed_html)"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "HX-M9Im_dneG"
      },
      "cell_type": "markdown",
      "source": [
        "#Interact with a specific player"
      ]
    },
    {
      "metadata": {
        "id": "ESJ1l7_Kt5Uj"
      },
      "cell_type": "code",
      "source": [
        "sim_to_interact = 'Alice'  # @param ['Alice', 'Bob','Charlie', 'Dorothy', 'Ellen'] {type:\"string\"}\n",
        "user_identity = 'a close friend'  # @param {type:\"string\"}\n",
        "interaction_premise = f'{sim_to_interact} is talking to {user_identity}\\n'  # @param {type:\"string\"}\n",
        "\n",
        "player_names = [player.name for player in players]\n",
        "player_by_name = {player.name: player for player in players}\n",
        "selected_player = player_by_name[sim_to_interact]\n",
        "interrogation = interaction_premise"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "5Q1cYflLt5Uj"
      },
      "cell_type": "code",
      "source": [
        "utterence_from_user = 'Did you manage to sell any magic beans?'  # @param {type:\"string\"}\n",
        "\n",
        "interrogation += f'{user_identity}: {utterence_from_user}'\n",
        "player_says = selected_player.say(interrogation)\n",
        "interrogation += f'\\n{sim_to_interact}: {player_says}\\n'\n",
        "print(interrogation)"
      ],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "9D43NMru3qjQ"
      },
      "cell_type": "code",
      "source": [],
      "outputs": [],
      "execution_count": null
    },
    {
      "metadata": {
        "id": "4XsTfvpn0JhC"
      },
      "cell_type": "markdown",
      "source": [
        "```\n",
        "Copyright 2023 DeepMind Technologies Limited.\n",
        "\n",
        "Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "you may not use this file except in compliance with the License.\n",
        "You may obtain a copy of the License at\n",
        "\n",
        "    https://www.apache.org/licenses/LICENSE-2.0\n",
        "\n",
        "Unless required by applicable law or agreed to in writing, software\n",
        "distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "See the License for the specific language governing permissions and\n",
        "limitations under the License.\n",
        "```"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "last_runtime": {
        "build_target": "",
        "kind": "private"
      },
      "private_outputs": true,
      "provenance": [],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
